﻿namespace JobButenko.Models.BusinessLogicLayer
{
    using System;
    using System.Linq;
    using System.Net;
    using System.Net.Mail;
    using System.Security.Cryptography;
    using System.Web.Security;

    public class UserRepository
    {
        private readonly JobDataContext dataContext;

        public UserRepository(JobDataContext dataContext)
        {
            this.dataContext = dataContext;
        }

        private User GetUser(string username)
        {
            var user = this.dataContext.Users.FirstOrDefault(x => x.UserName.ToLower().Equals(username.ToLower()));

            return user;
        }

        public User CreateUser(string username, string password, string email, bool isApproved)
        {
            var passwordSalt = CreateSalt();
            var user = new User
                           {
                               UserName = username,
                               Email = email,
                               PasswordSalt = passwordSalt,
                               Password = CreatePasswordHash(password, passwordSalt),
                               CreatedDate = DateTime.Now,
                               IsActivated = isApproved,
                               NewEmailKey = GenerateKey()
                           };

            this.dataContext.Users.InsertOnSubmit(user);
            this.Save();
            if (!isApproved)
            {
                this.PostActivateCode(user);
            }

            return this.GetUser(username);
        }

        public void PostActivateCode(User user)
        {
            if (user.NewEmailKey != null)
            {
                var activationLink = "http://localhost:17179/Account/Activate?username=" +
                                    user.UserName + "&key=" + user.NewEmailKey;

                var message = new MailMessage("jobbutenko@gmail.com", user.Email)
                {
                    Subject = "Activate your account",
                    Body = activationLink
                };

                var client = new SmtpClient("smtp.gmail.com")
                {
                    Credentials = new NetworkCredential("jobbutenko@gmail.com", "qwertyqaz"),
                    EnableSsl = true
                };
                client.Send(message);
            }
        }

        public void AddUserToRole(int userId, int roleId)
        {
            var userRole = new UserRole
                               {
                                   RoleId = roleId,
                                   UserId = userId
                               };
            this.dataContext.UserRoles.InsertOnSubmit(userRole);
            this.Save();
        }

        public bool ActivateUser(string username, string key)
        {
            var user = this.dataContext.Users.SingleOrDefault(u => u.UserName == username);

            if (user != null)
            {
                if (user.NewEmailKey == key)
                {
                    user.IsActivated = true;
                    user.NewEmailKey = null;
                    this.Save();
                    return true;
                }

                return false;
            }

            return false;
        }

        private static string CreateSalt()
        {
            var rng = new RNGCryptoServiceProvider();
            var buff = new byte[32];
            rng.GetBytes(buff);

            return Convert.ToBase64String(buff);
        }

        private static string CreatePasswordHash(string password, string salt)
        {
            var saltAndPassword = string.Concat(password, salt);
            return FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPassword, "sha1");
        }

        public bool ValidateUser(string username, string password)
        {
            var user = this.dataContext.Users.SingleOrDefault(u => u.UserName == username);

            if (user != null)
            {
                return user.Password == CreatePasswordHash(password, user.PasswordSalt);
            }

            return false;
        }

        private static string GenerateKey()
        {
            var emailKey = Guid.NewGuid();
            return emailKey.ToString();
        }

        public User GetDbUser(string userName)
        {
            return this.dataContext.Users.SingleOrDefault(x => x.UserName == userName);
        }

        private void Save()
        {
            this.dataContext.SubmitChanges();
        }

        public UserRole GetRoleUser(string userName)
        {
            var user = this.GetDbUser(userName);
            return user != null ? this.dataContext.UserRoles.SingleOrDefault(r => r.UserId == user.UserId) : null;
        }
    }
}